package com.zg.paging3.activity.net

import android.app.ProgressDialog
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import androidx.paging.LoadState
import androidx.recyclerview.widget.LinearLayoutManager
import com.zg.paging3.R
import com.zg.paging3.activity.net.adapter.NetDataAdapter
import com.zg.paging3.activity.net.other.HeaderLoadStateAdapter
import com.zg.paging3.activity.net.other.TestLoadStateAdapter
import com.zg.paging3.databinding.ErrorLayoutBinding
import kotlinx.android.synthetic.main.activity_net_data.*
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

/***
 * 1.创建Retrofit的工具类和基类response以及model
 * 2.创建 NetDataRepositroty : 请求网络数据
 * 3.创建 NetDataSource : PagingSource
 * 4.创建 NetDataViewModel : Pager、PagingData
 * 5.创建rv适配器 NetDataAdapter : PagingDataAdapter
 * 6.NetDataActivity使用 请求的数据
 * 7.增加刷新。使用SmartRefreshLayout，
 * 8.适配器添加头部和尾部 https://developer.android.com/codelabs/android-paging#9 这个之后在研究吧
 * 9.小结：
 *  PagingSource：负责提供源数据，一般是网络请求或者数据库查询，
    PagingData：分页数据的容器，负责一些分页的参数设定和订阅源数据流
    PagingDataAdapter：跟常规的RecyclerivewAdapter一样把数据转换成UI
    LoadStateAdapter：可以添加页头/页脚，方便实现loadmore的样式
 * 10.参考地址：https://blog.csdn.net/weixin_42046829/article/details/110140424
 * https://www.jianshu.com/p/8de75e1ff321
 * https://juejin.cn/post/6898133386218045453
 * https://juejin.cn/post/6929126825973022727
 * https://blog.csdn.net/vitaviva/article/details/109400331
 * 封装：
 * https://www.jianshu.com/p/7684fc2d4277
 * https://juejin.cn/post/6936889079393058847/
 *
 * https://mp.weixin.qq.com/s/qBxhtgjLluUZsHCinNHUAQ
 * https://www.wanandroid.com/article/query?k=paging3
 * https://cn.bing.com/search?q=android+paging3&qs=AS&pq=android+paging&sk=AS1&sc=8-14&cvid=76479D451E0848EFAF71333244DA7FCA&FORM=QBLH&sp=2
 * OkHttp拦截器获取GET/POST请求参数并添加公共参数 https://blog.csdn.net/ysy950803/article/details/94778870
 *
 */
class NetDataActivity : AppCompatActivity() {

    private val TAG = "zxd"

    private val vm: NetDataViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_net_data)
        netRv.layoutManager = LinearLayoutManager(this)
        val adapter = NetDataAdapter(this)
        netRv.adapter = adapter
        //adapter.submitData 是一个协程挂起（suspend）操作，所以要放入协程赋值
        //请求数据，然后adapter提交数据
        lifecycleScope.launch {
            vm.articleList.collectLatest {
                adapter.submitData(it)
            }
        }

        //一般来说，对于可下拉刷新或者上拉加载更多的视图，我们都会用第三方框架，这样会更好处理，并且有默认写好的上拉或下拉的样式。以SmartRefreshLayout为例：
        // 数据加载状态的回调
        /*var currentStates: LoadStates? = null
        adapter.addLoadStateListener { state: CombinedLoadStates ->
            currentStates = state.source
            // 如果append没有处于加载状态，但是refreshLayout出于加载状态，refreshLayout停止加载状态
            if (state.append is LoadState.NotLoading && srl.isLoading) {
                srl.finishLoadMore()
            }
            // 如果refresh没有出于加载状态，但是refreshLayout出于刷新状态，refreshLayout停止刷新
            if (state.source.refresh is LoadState.NotLoading && srl.isRefreshing) {
                srl.finishRefresh()
            }
        }

        srl.setRefreshHeader(ClassicsHeader(this))
        srl.setRefreshFooter(ClassicsFooter(this))
        srl.setOnLoadMoreListener {
            // 如果当前数据已经全部加载完，就不再加载
            if (currentStates?.append?.endOfPaginationReached == true)
                srl.finishLoadMoreWithNoMoreData()
            else {
                adapter.retry()
                if (srl.isLoading)
                    srl.finishLoadMore()
            }
        }
        srl.setOnRefreshListener { adapter.refresh() }*/

        /***
         * addDataRefreshListener 这个方法是当新的PagingData被提交并且显示的回调
         * addLoadStateListener这个相较于上面那个比较复杂，listener中的回调会返回一个CombinedLoadStates对象
         *
         * 刷新状态的说明--CombinedLoadStates
         * refresh:LoadState：刷新时的状态，因为可以调用 PagingDataAdapter#refresh() 方法进行数据刷新。
         * append:LoadState：可以理解为 RecyclerView 向下滑时数据的请求状态。
         * prepend:LoadState：可以理解为RecyclerView 向上滑时数据的请求状态。
         * source 和 mediator 分别包含上面3个的属性，source 代表单一的数据源，mediator 代表多数据源的场景，source 和 mediator 二选一。
         *
         * 状态对应的类是 LoadState，它有三种状态：
         * Loading：数据加载中。
         * NotLoading：内存中有已经获取的数据，即使往下滑，Paging 也不需要请求更多的数据。
         * Error：请求数据时返回了一个错误。
         *
         * 注意：
         * 刷新失败处理
         *  直接调用刷新即可
         *  adapter.refresh()
            加载更多失败处理
            adapter.retry()
            为什么是重试？
            因为paging是无缝加载，所以没有手动上拉加载逻辑
            retry()虽然是重试，但是paging已处理，只有失败后会重试，所以这里上拉加载调用重试没问题
         */

        //打开界面，加载数据的时候显示loading，如果出数据了，那么隐藏掉对话框
        val dialog = ProgressDialog(this)
        dialog.setTitle("Loading......")
        dialog.setMessage("等待中...  加载出数据后自动隐藏")
        dialog.isIndeterminate = true
        dialog.setCancelable(false)
        adapter.addLoadStateListener {
            when (it.source.refresh) {
                //数据加载中。
                is LoadState.Loading -> {
                    dialog.show()
                    Log.i(TAG, "Loading: ---------------------")
                }
                //内存中有已经获取的数据，即使往下滑，Paging 也不需要请求更多的数据。
                is LoadState.NotLoading -> {
                    dialog.cancel()
                    Log.i(TAG, "NotLoading: +++++++++++++++")
                }
                //请求数据时返回了一个错误。
                is LoadState.Error -> {
                    dialog.cancel()
                    Log.i(TAG, "Error: ======================")
                    Toast.makeText(this, "出现错误", Toast.LENGTH_LONG).show()
                    val errorLayoutBinding = DataBindingUtil.inflate<ErrorLayoutBinding>(
                        layoutInflater,
                        R.layout.error_layout,
                        cl,
                        true
                    )
                    errorLayoutBinding.retryBtn.setOnClickListener {
                        cl.removeView(errorLayoutBinding.root)
                        adapter.refresh()
                    }
                }
            }
        }

        /***
         * LoadStateAdapter：可以添加页头/页脚，方便实现loadmore的样式
         * fun withLoadStateHeader(header: LoadStateAdapter<*> ) 头部添加状态适配器
         * fun withLoadStateFooter(footer: LoadStateAdapter<*> ) 底部添加状态适配器
         * fun withLoadStateHeaderAndFooter(header: LoadStateAdapter<>, footer: LoadStateAdapter<> ) 头尾都添加状态适配器
         * 谷歌出过一个 MergeAdapter，就是把多个RecyclerView.Adapter 合并成一个
         */
        netRv.adapter = adapter.withLoadStateHeaderAndFooter(
            TestLoadStateAdapter(adapter),
            HeaderLoadStateAdapter(adapter)
        )

    }
}